package se.sweco.dataservice.impl;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import se.sweco.dataservice.Coord;
import se.sweco.dataservice.TrafficData;

public class XMLDataHandler extends DefaultHandler {
	private static final String DEFAULT_ERROR = "Malformed XML response.";

	private List<TrafficData> trafficData;
	private double taxRate;
	private String error;
	
	private double startLat, endLat, startLon, endLon;
	private double time;
	private int reliability;

	private StringBuffer sb;

	public List<TrafficData> getTrafficData() {
		return trafficData;
	}
	
	public double getTaxRate() {
		return taxRate;
	}
	
	public boolean hasError() {
		return !(error == null || error.isEmpty());
	}
	
	public String getError() {
		return error;
	}

	public void startDocument() {
		trafficData = new ArrayList<TrafficData>();
		taxRate = 0;
		error = null;
		sb = new StringBuffer();
	}

	public void startElement(String ns, String localName, String qName, Attributes attr) throws SAXException {
		if (hasError()) {
			return;
		}

		sb.setLength(0);
		if (localName.equals("tax")) {
			taxRate = -1;
		} else if (localName.equals("traffic")) {
			startLat = -1;
			startLon = -1;
			endLat = -1;
			endLon = -1;
			time = -1;
			reliability = -1;
		}
	}
	
	public void endElement(String namespaceURI, String localName, String qName) {
		if (hasError()) {
			return;
		}
		
		/* Error */
		if (localName.equals("error")) {
			error = sb.toString();
			if (!hasError()) {
				error = DEFAULT_ERROR;
			}
		} else
		/* Tax data */
		if (localName.equals("tax")) {
			if (taxRate < 0) {
				error = DEFAULT_ERROR;
			}
		} else if (localName.equals("tariff")) {
			taxRate = Double.parseDouble(sb.toString().trim());
		} else
		/* Traffic data */
		if (localName.equals("traffic")) {
			if (startLat > 0 && startLon > 0 && endLat > 0 && endLon > 0 && time > 0 && reliability > 0) {
				Coord start = new Coord(startLon, startLat);
				Coord end = new Coord(endLon, endLat);
				TrafficData data = new TrafficData(start, end, time, reliability);
				trafficData.add(data);
			} else {
				error = DEFAULT_ERROR;
			}
		} else if (localName.equals("startLat")) {
			startLat = Double.parseDouble(sb.toString().trim());
		} else if (localName.equals("startLon")) {
			startLon = Double.parseDouble(sb.toString().trim());
		} else if (localName.equals("endLat")) {
			endLat = Double.parseDouble(sb.toString().trim());
		} else if (localName.equals("endLon")) {
			endLon = Double.parseDouble(sb.toString().trim());
		} else if (localName.equals("time")) {
			time = Double.parseDouble(sb.toString().trim());
		} else if (localName.equals("reliability")) {
			reliability = Short.parseShort(sb.toString().trim());
		}
	}
	
	public void characters(char[] buf, int start, int len) {
		sb.append(buf, start, len);
	}
}
